import base64
import json
from io import BytesIO
from PIL import Image as PILImage
from ..models import Image
from middleware.cache_service import CacheService


import base64
import json
from io import BytesIO
from PIL import Image as PILImage
from ..models import Image
from middleware.cache_service import CacheService


class ImageService:
    @staticmethod
    def set_image_cache(image_id, image_binary, mime_type):
        """
        将原始二进制图片转为 Base64 并写入缓存。
        :param image_id: 图片 ID
        :param image_binary: 原始二进制数据
        :param mime_type: MIME 类型
        """
        base64_data = base64.b64encode(image_binary).decode('utf-8')
        cache_value = {
            "image_data": base64_data,
            "mime_type": mime_type
        }
        CacheService.set("image", image_id, json.dumps(cache_value))

    @staticmethod
    def get_image_from_cache(image_id):
        """
        从缓存中获取 Base64 图片数据并解码为原始二进制。
        :param image_id: 图片 ID
        :return: { "image_data": bytes, "mime_type": str } 或 None
        """
        cached_value = CacheService.get("image", image_id)
        if not cached_value:
            return None
        data = json.loads(cached_value)
        image_binary = base64.b64decode(data["image_data"])
        return {
            "image_data": image_binary,
            "mime_type": data["mime_type"]
        }

    @staticmethod
    def get_image(image_id):
        """
        获取图片（优先缓存，其次数据库），返回原始二进制图片数据。
        :param image_id: 图片 ID
        :return: { "image_data": bytes, "mime_type": str } 或 None
        """
        # 先查缓存
        cached = ImageService.get_image_from_cache(image_id)
        if cached:
            return cached

        # 再查数据库
        image = Image.objects.filter(pk=image_id).first()
        if not image:
            return None

        # 回写缓存
        ImageService.set_image_cache(image_id, image.image_data, image.mime_type)

        # 返回原始二进制数据
        return {
            "image_data": image.image_data,
            "mime_type": image.mime_type
        }

    @staticmethod
    def add_image(image_binary, mime_type):
        """
        插入新图片，输入是原始二进制图片数据。
        验证后直接保存到数据库，并更新缓存。
        :param image_binary: 原始二进制图片数据
        :param mime_type: MIME 类型
        :return: 新插入的 image_id
        """
        # 验证图片有效性
        try:
            img = PILImage.open(BytesIO(image_binary))
            img.verify()
        except Exception as e:
            raise ValueError(f"无效的图片格式: {e}")

        # 重新打开用于压缩或处理
        img = PILImage.open(BytesIO(image_binary))
        output_buffer = BytesIO()
        img.save(output_buffer, format=img.format)  # 可选压缩
        compressed_binary = output_buffer.getvalue()

        # 存入数据库
        db_image = Image.objects.create(
            image_data=compressed_binary,
            mime_type=mime_type
        )

        # 更新缓存
        ImageService.set_image_cache(db_image.image_id, compressed_binary, mime_type)

        return db_image.image_id